
package ChatNI;

import ChatController.ChatController;
import common.Hello;
import common.Text;
import common.TransfertFileRequest;
import common.Fichier;
import common.TransfertFileAccept;
import common.Bye;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.net.*;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *Classe servant pour l'écoute du médium pour une communication via UDP
 * @author Marion et Nicolas
 */
public class UDPecoute implements Runnable {

    private DatagramSocket datagrameSocket;
    private Thread thread;
    private Boolean communication = false;

    /**
     * Le constructeur lance le thread pour la communication
     */
    public UDPecoute (){
       try {
                datagrameSocket = new DatagramSocket(ChatNI.numPortUDPecoute);
                communication=true;
                thread = new Thread(this);
        }
        
        catch (Exception e){
            System.out.println("Erreur dans le constructeur UDPecoute");
        }
    }

  /**
   * Réception d'un message transmis via UDP
   * @param message 
   */
    private void receiveMessage (Object message){
        // On fait des instanceof du message reçu pour ensuite le caster selon le type
        // Ensuite, on peut traiter selon le cas le message
      try {  
            if (message instanceof Hello && ChatNI.listening){
                    Hello mess2 = (Hello) message;
                    System.out.println("Paquet hello reçu => Nom : "+ mess2.getUsername()+" ; Adresse : " + mess2.getAddr()+" Booleen = "+mess2.getReply());
                    if(mess2.getAddr().equals(InetAddress.getLocalHost()))
                        System.out.println("C'est un packet HELLO venant de moi, je m'en occupe pas");
                        
                    else if (mess2.getReply()) {
                            ChatNI.control.newUser(mess2.getUsername(), mess2.getAddr(),true);
                            System.out.println("Le controller à bien traité le helloTrue");
                    } else 
                            ChatNI.control.newUser(mess2.getUsername(), mess2.getAddr(),false);
                    
                    
                    
            } else if(message instanceof Bye && ChatNI.listening) {

                    Bye mess2 = (Bye) message;
                    System.out.println("Paquet bye reçu => Adresse : " + mess2.getAddr());
                    if(mess2.getAddr().equals(InetAddress.getLocalHost()))
                        System.out.println("C'est un packet BYE venant de moi, je m'en occupe pas");
                    else
                        ChatNI.control.byeUser(mess2.getAddr());
                    System.out.println("Le controller à bien traité le bye");
                  
                    

            } else if(message instanceof TransfertFileRequest && ChatNI.listening) {
                    TransfertFileRequest mess2 = (TransfertFileRequest) message;
                    // TODO: Afficher à l'utilisateur la demande de transfert de fichier
            
           
            } else if(message instanceof TransfertFileAccept && ChatNI.listening) {
                    TransfertFileAccept mess2 = (TransfertFileAccept) message;
            
           
            } else if(message instanceof Text && ChatNI.listening) {
                     Text mess2 = (Text) message;
                     
                     if(mess2.getAddr().equals(InetAddress.getLocalHost()))
                        System.out.println("C'est un packet TEXT venant de moi, je m'en occupe pas");
                     else {
                        System.out.println("Paquet texte reçu => Adresse : " + mess2.getAddr());
                        ChatNI.control.textReceived(mess2.getAddr(),mess2.getContent());
                        System.out.println("Le controller à bien traité le message texte");
                     }
            
           
            } else if(message instanceof Fichier && ChatNI.listening) {
                    Fichier mess2 = (Fichier) message;
                    // TODO : Enregistrer le fichier dans l'ordi
            
           
            }
            
            
       } catch (Exception e){
                System.out.println("Erreur dans le traitement d'un packet UDP");
         }
    }
    
    /**
     * Cette méthode converti les octets en "Objets" qui pourront ensuite être instanciés en types de Message
     * @param tablOctets
     * @return 
     */
    private Object bytesToMessage (byte[] tablOctets) {
        try {
          ByteArrayInputStream byteArray = new ByteArrayInputStream(tablOctets);
          ObjectInputStream ois = new ObjectInputStream(byteArray);   
          return ois.readObject();                               
      } catch (Exception e){
          System.out.println("Erreur de conversion des bytes en Message");
          return null;
      }
    }

    /**
     * Méthode qui écoute le réseau
     * Elle reçoit un paquet, en extrait les données, et les convertit en Objet
     * Ensuite, elle fait appel à la méthode receiveMessage pour déterminer le type de message reçu
     */
    @Override
    public void run() {
        while (communication == true) {
            try {
                byte[] tablOctets = new byte[500];
                DatagramPacket packet = new DatagramPacket(tablOctets,500);
                datagrameSocket.receive(packet);
                Object mess = bytesToMessage(packet.getData());
                receiveMessage(mess);

            } catch (IOException ex) {
                Logger.getLogger(UDPecoute.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }
    
    /**
     * Début de l'écoute udp
     */
    protected void start(){
        communication = true;
        thread.start();
    }
    
    /**
     * Arrêt de l'écoute udp
     */
    protected void stop(){
        communication = false;  // On écoute plus le réseau
        thread.interrupt();
        datagrameSocket.close();

    }

}
